<?php

namespace tmcore\services\upload\driver;

use tmcore\exceptions\UploadException;
use tmcore\services\upload\BaseUpload;
use OSS\OssClient;

/**
 * 阿里云存储引擎 (OSS)
 */
class Aliyun extends BaseUpload
{
    protected $ossClient;

    /**
     * 初始化
     * @param array $config
     * @return mixed|void
     */
    protected function initialize(array $config)
    {
        parent::initialize($config);
    }

    /**
     * 上传文件
     * @param string $name 文件对象 name
     * @param array $rule 上传规则 ['fileSize' => 0, 'fileExt' => 'jpg', 'image' => '200,200,jpg']
     * @param string $file_type 文件类型
     * @return bool|array
     * @throws UploadException
     */
    public function upload(string $name, array $rule, string $file_type = 'image') {

        try {
            //接受文件
            $file = $this->getFileInfo($name);
            //验证文件
            $this->validate($name, $rule);

            $this->ossClient = new OssClient($this->fileConfig['accessKeyId'], $this->fileConfig['accessKeySecret'], $this->fileConfig['endpoint']);

            $file_path = $file->getRealPath();

            //上传文件
            $result = $this->ossClient->uploadFile($this->fileConfig['bucket'], $this->getSavePath($file_type) . '/' . $this->fileInfo['fileName'], $file_path);
            if(empty($result['info']['url'])) throw new \Exception('上传阿里云失败');

            $this->fileInfo['size'] = $result['info']['size_upload'];
            $this->fileInfo['url'] = $result['info']['url'];

            return $this->fileInfo;

        } catch (UploadException $e) {
            throw new UploadException($e->getMessage());
        } catch (\Exception $e) {
            throw new UploadException($e->getMessage());
        }
    }

    /**
     * 远程文件下载存储
     * @param string $url 文件路径
     * @param string $file_type 文件类型
     * @return array
     * @throws UploadException
     */
    public function fetch(string $url, string $file_type = 'image') {

        try {

            $ext = $this->getFileExt($url);

            $file_name = $this->buildSaveName($ext);

            $file_content = file_get_contents($url);;

            //上传文件
            $result = $this->ossClient->putObject($this->fileConfig['bucket'], $this->getSavePath($file_type) . '/' . $file_name, $file_content);
            if(empty($result['info']['url']))throw new \Exception('文件上传阿里云失败');

            $this->fileInfo['url'] = $result['info']['url'];

            return [
                'ext'          => $ext,
                'size'         => strlen($file_content),
                'md5'          => '',
                'sha1'         => '',
                'originalName' => preg_replace('/^.+[\\\\\\/]/', '', $url),
                'fileName'     => $file_name,
                'url'          => $result['info']['url']
            ];

        } catch (\Exception $e) {
            throw new UploadException($e->getMessage());
        }
    }

    /**
     * 批量上传文件
     * @param string $name 文件对象 name
     * @param array $rule 上传规则 ['fileSize' => 0, 'fileExt' => 'jpg', 'image' => '200,200,jpg']
     * @param string $file_type 文件类型
     * @return array
     * @throws UploadException
     */
    public function batchUpload(string $name, array $rule, string $file_type = 'image') {

        try {
            //接受文件
            $files = $this->getFileInfo($name, true);
            //循环检验
            foreach($files as $file) {
                $this->validate($name, $rule, $file);
            }

            $this->ossClient = new OssClient($this->fileConfig['accessKeyId'], $this->fileConfig['accessKeySecret'], $this->fileConfig['endpoint']);

            foreach($files as $key => $file) {
                //上传oss文件
                $result = $this->ossClient->uploadFile($this->fileConfig['bucket'], $this->getSavePath($file_type) . '/' . $file['fileName'], $file['file']->getRealPath());
                if(empty($result['info']['url'])) throw new \Exception('文件上传阿里云失败');
                $this->fileInfo[$key]['url'] = $result['info']['url'];
            }

            return $this->fileInfo;

        } catch (UploadException $e) {
            throw new UploadException($e->getMessage());
        } catch (\Exception $e) {
            throw new UploadException($e->getMessage());
        }
    }

    /**
     * 删除文件
     * @param string $path 文件路径
     * @return bool
     * @throws UploadException
     */
    public function delete(string $path) {
        try {
            $this->ossClient = new OssClient($this->fileConfig['accessKeyId'], $this->fileConfig['accessKeySecret'], $this->fileConfig['endpoint']);

            //上传oss文件
            $result = $this->ossClient->deleteObject($this->fileConfig['bucket'], $path);
            if(!$result) throw new \Exception('删除文件失败');
            return true;
        } catch (\Exception $e) {
            throw new UploadException($e->getMessage());
        }
    }
}